#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "RawParser.h"
#include <iostream>
using namespace std;

#define RAW_LENGTH 16

typedef unsigned char BYTE;

RawParser::RawParser(const char* filePath, int width, int height)
    :m_imageW(width)
    , m_imageH(height)
    , m_bHasPreload(false)
{
    errno_t err;

    if ((err = fopen_s(&m_imageFP,filePath, "rb")) != 0)
    {
        m_fileSize = 0;
        printf("can not open the raw image");
        return;
    }
    else
    {
        //读取文件总大小
        fseek(m_imageFP, 0, SEEK_END);
        m_fileSize = ftell(m_imageFP);
        fseek(m_imageFP, 0, SEEK_SET);
    }
}


RawParser::~RawParser()
{
    if (m_imageFP)
    {
        fclose(m_imageFP);
    }
}

bool RawParser::preloadRaw()
{
    char* _content = (char*)malloc(m_fileSize);
    if (!_content)
    {
        return false;
    }

    size_t _cnt = fread(_content, 1, m_fileSize, m_imageFP);
    if (_cnt != m_fileSize)
    {
        free(_content);
        return false;
    }
    m_rawData.assign(_content, _cnt);
    m_bHasPreload = true;
    return true;
}

bool RawParser::getPointTemperature(int x, int y, int& temperature)
{
    if (m_bHasPreload)
    {
        if (m_rawData.empty())
        {
            return false;
        }
    }
    else
    {
        if (!m_imageFP)
        {
            return false;
        }
    }
    if (m_imageW <= x)
    {
        return false;
    }
    if (m_imageH <= y)
    {
        return false;
    }
    unsigned char tmpValue[2];
    long _offset = (m_imageW * y + x) * 2;//每个温度数据占用两个字节16位
    if (m_fileSize < _offset)
    {
        return false;
    }

    if (m_bHasPreload)
    {
        tmpValue[0] = m_rawData.at(_offset);
        tmpValue[1] = m_rawData.at(_offset + 1);
    }
    else
    {
        fseek(m_imageFP, _offset, 0);
        //从像素坐标对应的文件位置读出两个字节数据
        size_t _ret = fread(tmpValue, 1, 2, m_imageFP);
        if (_ret != 2)
        {
            return false;
        }
    }

    temperature = tmpValue[1];
    //字节序转换
    temperature = temperature << 8;
    temperature = temperature + (tmpValue[0]);
    return true;
}

bool RawParser::rangeCaculate(RectArea rect IN, float& temperature OUT, PixTemperature& maxPT OUT, PixTemperature& minPT OUT)
{
    if (m_bHasPreload)
    {
        if (m_rawData.empty())
        {
            return false;
        }
    }
    else
    {
        if (!m_imageFP)
        {
            return false;
        }
    }
    if (rect.x < 0
        || rect.y < 0
        || rect.w < 0
        || rect.h < 0
        || rect.x > m_imageW
        || rect.y > m_imageH
        || (rect.x + rect.w) > m_imageW
        || (rect.y + rect.h) > m_imageH)
    {
        return false;
    }
    PixPoint maxTPP, minTPP, bottomRight;
    int maxTemp, minTemp;
    bool pointsReady = false;//最高最低温度初始化标记
    //fseek(m_imageFP, 0, 0);
    long pointCount = 0;
    unsigned char _temp[2];
    //所有点温度之和。使用__int64保存结果足够保证计算时不会溢出，
    //温度保存16位，范围是±32767，_int64表示范围是±9,223,372,036,854,775,808
    //按照最大值计算，可保存281,474,976,710,656个数据之和
    //一张1080*1080的图片只有1,166,400个像素
    __int64 _temperature = 0;
    int pointTemp;//点温度
    bottomRight.x = rect.x + rect.w;
    bottomRight.y = rect.y + rect.h;
    for (int x = rect.x; x < bottomRight.x; ++x)
    {
        for (int y = rect.y; y < bottomRight.y; ++y)
        {
            long _index = pointToIndex(x, y);
            if (m_fileSize < _index)
            {
                return false;
            }

            if (m_bHasPreload)
            {
                _temp[0] = m_rawData.at(_index);
                _temp[1] = m_rawData.at(_index + 1);
            }
            else
            {
                fseek(m_imageFP, _index, 0);
                fread(_temp, 1, 2, m_imageFP);
            }

            pointTemp = ((_temp[1] << 8) & 0xFF00);
            pointTemp += _temp[0];
            //判断最高、最低温度并记录坐标
            if (pointsReady)
            {
                if (pointTemp < minTemp)
                {
                    minTemp = pointTemp;
                    minTPP.x = x;
                    minTPP.y = y;
                }
                else if (pointTemp > maxTemp)
                {
                    maxTemp = pointTemp;
                    maxTPP.x = x;
                    maxTPP.y = y;
                }
            }
            else
            {
                //最高、最低温度初始化为第一个点的温度
                minTemp = pointTemp;
                minTPP.x = x;
                minTPP.y = y;
                maxTemp = pointTemp;
                maxTPP.x = x;
                maxTPP.y = y;
                pointsReady = true;
            }
            _temperature += pointTemp;
            ++pointCount;
        }
    }
    if (pointCount == 0)
    {
        return false;
    }
    temperature = _temperature / pointCount * 0.1;
    maxPT.point = maxTPP;
    maxPT.temperature = maxTemp;
    minPT.point = minTPP;
    minPT.temperature = minTemp;
    return true;
}

bool RawParser::rangeCaculate(RectArea rect IN, float& temperature OUT)
{
    PixTemperature maxPT, minPT;
    return rangeCaculate(rect, temperature, maxPT, minPT);
}

long RawParser::pointToIndex(int x, int y)
{
    if (m_imageW <= x)
    {
        return false;
    }
    return ((m_imageW * y + x) * 2);//每个温度数据占用两个字节16位
}



